忒修斯之船的題目是不斷的替換掉船上的材料,為了能顯示這個替換的過程,我打算用「顏色」的變化,來做材料替換的呈現。
規格:
船的 UI 變化規格:
如果希望在「一張圖」裡面,讓顏色進行變化,的確是可以做到,大概需要用到 mask 來處理。不過如果只是想要呈現顏色變化,我想實作的方式是,上下兩張圖疊起來。一開始上面的圖是不透明度 1,下面的圖不透明度是 0 。隨著材料被替換的過程,上面的圖不透明度往 0 開始靠近,下面的圖不透明度往1開始靠近。最後,上面的圖不透明度是 0,下面的圖不透明度是1。
/// 船
private var upShipImage: some View {
Image(systemName: "ferry.fill")
.renderingMode(.template)
.foregroundColor(upShipColor)
.font(.system(size: 200))
}
private var downShipImage: some View {
Image(systemName: "ferry.fill")
.renderingMode(.template)
.foregroundColor(downShipColor)
.font(.system(size: 200))
}
整個 View 包含滑動的桿,程式碼如下
import SwiftUI
struct ShipView: View {
private var upShipColor: Color {
Color(white: 0, opacity: opacity)
}
@State private var opacity: Double = 1.0
private var downShipColor: Color {
Color(red: 1.0, green: 0, blue: 0, opacity: 1 - opacity)
}
private var progressString: String {
"材料更換程度: \(percentageString) %"
}
private var percentageString: String {
let opacityDouble = opacity * 100
return String(format: "%.1f", opacityDouble)
}
var body: some View {
VStack {
Text("Ship of Theseus")
.font(.largeTitle)
.padding()
Text(progressString)
.font(.title2)
.padding()
ZStack {
upShipImage
downShipImage
}
Slider(
value: $opacity,
in: 0.0...1.0,
step: 0.1
)
.padding()
}
}
private var upShipImage: some View {
Image(systemName: "ferry.fill")
.renderingMode(.template)
.foregroundColor(upShipColor)
.font(.system(size: 200))
}
private var downShipImage: some View {
Image(systemName: "ferry.fill")
.renderingMode(.template)
.foregroundColor(downShipColor)
.font(.system(size: 200))
}
}
struct ShipView_Previews: PreviewProvider {
static var previews: some View {
ShipView()
}
}
來看一下 0% 和 100% 時的 UI